use async_trait::async_trait;
use clap::Parser;
use reqwest::StatusCode;
use serde::Deserialize;

use crate::commands::commands::Command;
use crate::models::models::command::CommandState;
use crate::utils::command;

#[derive(Debug, Default, Clone, Parser)]
#[clap(disable_help_flag = true)]
struct Args {
    // 查询源
    #[arg(short = 's', long = "source", default_value = "ip-api")]
    source: String,
    value: String,
}

#[derive(Debug, Default, Clone)]
pub(crate) struct IpCommand {}

#[async_trait]
impl Command for IpCommand {
    async fn execute(&self, command: crate::models::models::command::Command) -> crate::models::models::command::Command {
        let args = command::parse_command_args::<Args>(command.args.as_str());
        if args.is_err() {
            return self.save_command_output(command, CommandState::Success, args.unwrap_err().to_string());
        }

        let args = args.unwrap();

        match args.source.as_str() {
            "ip-api" => {
                let url = format!("http://ip-api.com/json/{}?lang=zh-CN", args.value);
                let response = reqwest::get(url).await;
                if response.is_err() {
                    let err = response.err().unwrap().to_string();
                    log::error!("查询Ip-Api失败: {}", err.as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("查询Ip-Api信息失败: {}", err.as_str()));
                }

                let response = response.unwrap();
                if StatusCode::OK != response.status() {
                    log::error!("查询Ip-Api失败: {}", response.status().as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("查询Ip-Api失败: {}", response.status().as_str()));
                }

                let response = response.json::<IpApiResponse>().await;
                if response.is_err() {
                    let err = response.err().unwrap().to_string();
                    log::error!("解析Ip-Api响应数据失败: {}", err.as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("解析Ip-Api响应数据失败: {}", err.as_str()));
                }

                let response = response.unwrap();
                if "success" != response.status {
                    log::error!("查询Ip-Api失败: Ip-Api返回错误状态: {}", response.status.as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("查询Ip-Api失败: Ip-Api返回错误状态: {}", response.status.as_str()));
                }

                self.save_command_output(command, CommandState::Success, format!("Ip: {} - 国家: {} - 地区: {} - 城市: {} - 邮编: {} - 运营商: {} - 经纬度: {},{} - 时区: {}", args.value, response.country, response.region, response.city, response.zip, response.isp, response.lon, response.lat, response.timezone))
            }
            "csdn" => {
                let url = format!("https://searchplugin.csdn.net/api/v1/ip/get?ip={}", args.value);
                let response = reqwest::get(url).await;
                if response.is_err() {
                    let err = response.err().unwrap().to_string();
                    log::error!("查询CSDN信息失败: {}", err.as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("查询CSDN信息失败: {}", err.as_str()));
                }

                let response = response.unwrap();
                if StatusCode::OK != response.status() {
                    log::error!("查询CSDN失败: {}", response.status().as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("查询CSDN失败: {}", response.status().as_str()));
                }

                let response = response.json::<CsdnApiResponse>().await;
                if response.is_err() {
                    let err = response.err().unwrap().to_string();
                    log::error!("解析CSDN响应数据失败: {}", err.as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("解析CSDN响应数据失败: {}", err.as_str()));
                }

                let response = response.unwrap();
                if 200 != response.code {
                    log::error!("查询CSDN失败: CSDN返回错误状态: {} - {}", response.code, response.msg.as_str());

                    return self.save_command_output(command, CommandState::Failed, format!("查询CSDN失败: CSDN返回错误状态: {} - {}", response.code, response.msg.as_str()));
                }

                self.save_command_output(command, CommandState::Success, format!("Ip: {} - 地址信息: {}", args.value, response.data.address))
            }
            _ => self.save_command_output(command, CommandState::Failed, "未受支持的数据来源".to_string())
        }
    }
}

#[derive(Debug, Default, Clone, Deserialize)]
struct IpApiResponse {
    status: String,
    country: String,
    region: String,
    city: String,
    zip: String,
    lat: f64,
    lon: f64,
    timezone: String,
    isp: String,
}

#[derive(Debug, Default, Clone, Deserialize)]
struct CsdnApiResponse {
    code: i32,
    msg: String,
    data: CsdnApiData,
}

#[derive(Debug, Default, Clone, Deserialize)]
struct CsdnApiData {
    address: String,
}